﻿#define PublicTaskField

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using EssIL;
using OmniKits.Core;
using System.Collections;
using System.Threading;
using System.Diagnostics;

namespace OmniKits.NanaTube
{
    public partial class NanaTubeAsync<T>
        where T : class
    {
        // Here comes MAGIC! DO NOT TOUCH if you have no clue about memory model and/or volatile read/write

        private class Holder
            : DisposableBase
        {
            private TaskCompletionSource<T> mTaskSource = new TaskCompletionSource<T>();
            public Holder Next; // not necessary to be volatile since all read is after SetResult
            public readonly Task<T> Task;
            public Holder()
            {
                Task = mTaskSource.Task;
            }


            public void SetData(T data)
            {
                var source = Interlocked.Exchange(ref mTaskSource, null);
                if (source == null)
                    return;

                source.SetResult(data);
            }

            protected override void Dispose(bool disposing)
            {
                var source = Interlocked.Exchange(ref mTaskSource, null);
                if (source == null)
                    return;

                Debug.WriteLine("Task #" + source.Task.Id + " Canceled");
                source.SetCanceled();
            }
        }
    }
}
